package controller;

import helper.Balance;
import helper.Calendr;
import helper.Formatter;
import helper.UserSession;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import model.CustomerDAO;
import model.FundDAO;
import model.Model;
import model.PositionDAO;
import model.TransactionDAO;

import org.mybeans.dao.DAOException;

import databeans.Customer;
import databeans.Employee;
import databeans.Fund;
import databeans.FundHistory;
import databeans.Position;
import databeans.Transaction;
import java.util.Map;

public class CustomerExchangeFundAction extends Action{
    private FundDAO fundDAO;
    private TransactionDAO transactionDAO;
    private CustomerDAO customerDAO;
    private PositionDAO positionDAO;
    
    public CustomerExchangeFundAction(Model model) {
        fundDAO = model.getFundDAO();
        transactionDAO = model.getTransactionDAO();
        customerDAO = model.getCustomerDAO();
        positionDAO = model.getPositoinDAO();
    }
    
    public String getName() {
        return "customerExchangeFund.do";
    }
    

    public String perform(HttpServletRequest request) {
        //ATTENTION
        // define target page
        String loginPageAjax   = "common/messages.jsp";
        String loginPage = "customer/customer-login.jsp";
        String originPage = "customer/exchange-funds.jsp";
        String successPage = originPage;

        //DecimalFormat twoDForm = new DecimalFormat("#.##");
        
        //set the employee
        Customer customer = null;
        Employee employee = null;
        Fund fundFrom = null;
        Fund fundTo = null;
        Position position = null;

        //errors and messages will be stored here
        //resetting those containers
        List<String> errors = new ArrayList<String>();
        List<String> messages = new ArrayList<String>();
   
        //define the error and message
        request.setAttribute("errors", errors);
        request.setAttribute("messages", messages);
        request.setAttribute("page", "fund-exchange");
        
        //get all the parameter from the form
        String requestType = request.getParameter("Submit");    
        String fundIDFrom = request.getParameter("txtFundIDFrom");
        String fundIDTo = request.getParameter("txtFundIDTo");
        String customerID = null;
        String submissionDate = Calendr.getTodayDateString();
        
        System.out.println("type = " + request.getParameter("type"));
        
        //check if employee has been logged in
        employee = UserSession.getLoggedInEmployee(request);      
        if (employee != null) {     
            UserSession.removeEmployeeFromSession(request);     
            errors.add("This section is closed for employee");      
            return loginPage ;      
           }

        //check if customer has actually logged in
        customer = UserSession.getLoggedInCustomer(request);
        if (customer == null) {
            errors.add("You need to log in");
            return loginPage ;
        }
        
        //Load all the fund
        try {
            Fund [] fundArray = fundDAO.getFunds();
            request.setAttribute("funds", fundArray);
            
            if (fundArray == null){
                messages.add("Currently there is no Fund you can select");
            }
        } catch (DAOException e2) {
            errors.add("funds could not be retrieved");
            errors.add("msg: "+ e2.getMessage());
            return originPage;
        }
        
        
        try {
            
            Position [] positionList = positionDAO.getPositions(customer.getCustomerID());
            HttpSession session = request.getSession(true); 
            
            if (positionList == null) {
                messages.add("There is no position for customer "+ customer.getFirstName() + " currently available to be seen");
                return successPage;
            }else
            {
                List<String> fundNames = new ArrayList<String>();
                
                System.out.println("Num of positions found = " + positionList.length);
                
                List<Long> remainingPositions = new ArrayList<Long> () ; 
               
                
                for(int i =0;i< positionList.length;i++)
                {
                    int fundID2 = positionList[i].getFundID();
                    System.out.println("fund ID = " + fundID2);
                    String name = fundDAO.lookup(fundID2).getName();
                    fundNames.add(name);
                    System.out.println("Fund name =" + name);
                    long userPendingTransactionTemp = Balance.getPendingPosition(fundID2, customer.getCustomerID());
                    System.out.println("userPendingTransactionTemp= " + userPendingTransactionTemp);
                    remainingPositions.add(userPendingTransactionTemp);
                }
                request.setAttribute("fundNames_p", fundNames);
                request.setAttribute("remainingPositionList", remainingPositions);
            }
            
            request.setAttribute("positionList", positionList);
        } catch (Exception e) {
            errors.add("Unable to retrieve customer's position");
            return originPage;
        }
        
        
        
        
        //reload all the fund
        try {
            //Fund [] fundArray = fundDAO.getFunds();
            Position[] positions = positionDAO.getPositions(customer.getCustomerID());
            //List<String,int> fundNames = new ArrayList<String>();
            Map<Object,String> fundNames=new HashMap<Object, String>();

            for (int i=0; i<positions.length; i++){
                //fundNames.add(fundDAO.lookup(positions[i].getFundID()).getName());
                fundNames.put(new Integer(fundDAO.lookup(positions[i].getFundID()).getFundID()), fundDAO.lookup(positions[i].getFundID()).getName());
            }
            request.setAttribute("fundNames", fundNames);
            
        } catch (DAOException e2) {
            errors.add("Funds could not be retrieved");
            return originPage;
        }

        
        //feed customer ID
        customerID = Integer.toString(customer.getCustomerID());

        // check for get or post request
        //if there is no parameter get passed, return to origin page
        if (requestType == null) {
            messages.add("Choose the fund and amount of shares to sell from that fund.");
            return originPage;     
        }
        
        //Long shares = Long.parseLong(request.getParameter("txtShares"));
        String shares = request.getParameter("txtShares");
        System.out.println("=================>> txtShares = " + shares);
        System.out.println("=================>> txtShares formated = " + Formatter.prepShareFromView(shares));
        
        //reload the form field
        request.setAttribute("txtFundIDFrom", fundIDFrom);
        request.setAttribute("txtFundIDTo", fundIDTo);
        request.setAttribute("txtShares", shares);
        
        //validate the input
        if (fundIDFrom.trim().equals("")) {
            //messages.add("Fund ID must be provided");
            errors.add("Please choose a Fund to exchange Shares from.");
            return originPage;
        }
        
        if (fundIDTo.trim().equals("")) {
            //messages.add("Fund ID must be provided");
            errors.add("Please choose a Fund to exchange Shares to.");
            return originPage;
        }
        
        if (fundIDFrom.trim().equals(fundIDTo.trim())) {
            //messages.add("Fund ID must be provided");
            errors.add("Please ensure fund To and From are different");
            return originPage;
        }

        
        if (customerID.trim().equals("")) {
            messages.add("Customer ID must be provided");
            errors.add("Current CustomerID field is still empty");
            return loginPage;
        }
        if (submissionDate.trim().equals("")) {
            messages.add("Submission Date must be provided");
            errors.add("Current Submission Date field is still empty");
            return originPage;
        } 

        
        //assume exchange has not been specified
        if (shares.trim().equals("")) {
            errors.add("Please specify amount of shares to sell");
            return originPage;
        }
        
        /*if (shares <= 0) {
            errors.add("Invalid Input. Please specify a valid amount of shares to sell");
            return originPage;
        }*/
        
        //feed customer ID
        customerID = Integer.toString(customer.getCustomerID());
        
        //reload that particular position
        try {
            position = positionDAO.lookup(Integer.parseInt(customerID), Integer.parseInt(fundIDFrom));
            request.setAttribute("position", position);
        } catch (DAOException e2) {
            errors.add("Customer position could not be retrieved");
            return originPage;
        }
        
        //check if customerid is valid
        try{
            customer = customerDAO.lookup(Integer.parseInt(customerID));
        } catch (NumberFormatException e1) {
            errors.add("Customer associated could not be retrieved - customer could not be read");
            return loginPage;
        } catch (DAOException efundtry) {
            errors.add("Customer associated could not be retrieved");
            return loginPage;
        }

        //check if fundid is valid
        try {
            fundFrom = fundDAO.lookup(Integer.parseInt(fundIDFrom));
            fundTo = fundDAO.lookup(Integer.parseInt(fundIDTo));
        } catch (NumberFormatException e1) {
            errors.add("Fund associated could not be retrieved - FundID could not be read");
            return originPage;
        } catch (DAOException efundtry) {
            errors.add("Fund associated could not be retrieved");
            return originPage;
        }
        
        //check if double and are correct double and in correct formatting
        //amount
        //shares
        int numOfDecimals = Formatter.numberOfDecimal(shares);
        
        System.out.println("numOfDecimals = " + numOfDecimals);
        if(numOfDecimals>3)
        {
            errors.add("Input is only allowed up to three decimal places. Please correct");
            return originPage;
        }
        
        if(Formatter.numberOfDecimal(shares)>3) {
            //messages.add("CFA only tracks shares number up to three decimal place. Please reenter the amount");
            errors.add("CFA only tracks shares number up to three decimal place. Please reenter the amount");
            return originPage;
        }
        if ( Double.parseDouble(shares) <= 0.00 ){
            //messages.add("The amount should not be negative");
            errors.add("Invalid input for Number of Shares to sell cannot be negative. Please check.");
            return originPage;
        }
        
        if (!Formatter.isDouble(shares)){
            //messages.add("You must input a number in amount field");
            errors.add("Invalid input in Amount field. Please check.");
            return originPage;
        }

        //check if the shares is actually OWNED by the customer
        Position userPositionFrom = null;
        try {
            //Fund [] fundArray = fundDAO.getFunds();
            userPositionFrom = (Position) positionDAO.getPosition(customer.getCustomerID(), Integer.parseInt(fundIDFrom));
            //List<String,int> fundNames = new ArrayList<String>();
        } catch (DAOException e2) {
            errors.add("Fund checking could not be performed");
            return originPage;
        }
        if (userPositionFrom == null){
            errors.add("User does not have the specified fund");
            return originPage;
        } else {
            System.out.println("User has fund " + userPositionFrom.getFundID() + " and id " + userPositionFrom.getCustomerID() + " and shares number " +  userPositionFrom.getShares()) ;
        }
        
        //check if customer has enough shares
        //user shares < user share position - sigma pending transaction)
        long userCurrentShares = userPositionFrom.getShares();
        long userPendingTransaction = Balance.getPendingPosition(Integer.parseInt(fundIDFrom), customer.getCustomerID());
        long maxSellingShares = userCurrentShares - userPendingTransaction;
        System.out.println("===> maxSellingShares = " + maxSellingShares);
        System.out.println("===> Formatter.prepShareFromView(shares) = " + Formatter.prepShareFromView(shares));
        
        if (Formatter.prepShareFromView(shares) > maxSellingShares ){
            System.out.println("Share from view for customer sell fund is " + Formatter.prepShareFromView(shares) );
            errors.add("Number of shares entered is greater than what you own. Please check.");
            return originPage;
        }
        /*
        if(numOfDecimals<3){
            if(numOfDecimals==2)
            {
                String s = shares.toString() + "0";
                System.out.println("2 decimals found. converting = " + s);
                shares = Long.parseLong(s);
            }
            else if(numOfDecimals==1)
            {
                String s = shares.toString() + "00";
                System.out.println("1 decimals found. converting = " + s);
                shares = Long.parseLong(s);
            }else if(numOfDecimals==0)
            {
                String s = shares.toString() + "000";
                System.out.println("No decimals found. converting = " + s);
                shares = Long.parseLong(s);
            }
        }*/
        
        // at this stage, all input validation should have been done
        try {
            

            Transaction tempTransFrom = new Transaction();
            tempTransFrom.setFundID(Integer.parseInt(fundIDFrom));
            tempTransFrom.setCustomerID(Integer.parseInt(customerID));
            tempTransFrom.setSubmissionDate(Calendr.getTodaysDate());
            tempTransFrom.setTransactionType(Transaction.EXCHANGE_SELL_ORDER);
            tempTransFrom.setShares(Formatter.prepShareFromView(shares));
            tempTransFrom = transactionDAO.create(tempTransFrom);
            

            Transaction tempTransTo = new Transaction();
            tempTransTo.setFundID(Integer.parseInt(fundIDTo));
            tempTransTo.setCustomerID(Integer.parseInt(customerID));
            tempTransTo.setSubmissionDate(Calendr.getTodaysDate());
            tempTransTo.setTransactionType(Transaction.EXCHANGE_BUY_ORDER);
            //tempTransTo.setShares(Formatter.prepShareFromView(shares));
            tempTransTo.setCorrespondingTransactionID(tempTransFrom.getTransactionID());

            //push those transaction object into database
            tempTransTo = transactionDAO.create(tempTransTo);
            
            
            tempTransFrom.setCorrespondingTransactionID(tempTransTo.getTransactionID());
            
            transactionDAO.update(tempTransFrom);
            //tempTrans.setAmount(Double.parseDouble(amount));
            
           
            // Attach (this copy of) the logged in employee bean to the session
            HttpSession session = request.getSession(true); 
            session.setAttribute("customer", customer );
            
            //set the welcome message
            //messages.add("Hi " + customer.getFirstName() + "!, you have succesfully placed " + tempTrans.getTransactionType() + " with ID " + tempTrans.getTransactionID() + "("+ fund.getSymbol() + ")!");
            messages.add("Your exchange order has been succesfully placed for <b>" + Formatter.prepShareToView(tempTransFrom.getShares()) + " shares</b> of <b>" + fundFrom.getName() +"</b> to <b>" + fundTo.getName() +"</b> to" );
            request.setAttribute("txtShares", "");
            
            try {
                
                Position [] positionList = positionDAO.getPositions(customer.getCustomerID());
                
                if (positionList == null) {
                    messages.add("There is no position for customer "+ customer.getFirstName() + " currently available to be seen");
                    return successPage;
                }else
                {
                	List<String> fundNames = new ArrayList<String>();
                	
                	System.out.println("Num of positions found = " + positionList.length);
                	
                	List<Long> remainingPositions = new ArrayList<Long> () ; 
                   
                	
                	for(int i =0;i< positionList.length;i++)
                	{
                		int fundID2 = positionList[i].getFundID();
                		System.out.println("fund ID = " + fundID2);
                		String name = fundDAO.lookup(fundID2).getName();
                		fundNames.add(name);
                		System.out.println("Fund name =" + name);
                		long userPendingTransactionTemp = Balance.getPendingPosition(fundID2, customer.getCustomerID());
                		System.out.println("userPendingTransactionTemp= " + userPendingTransactionTemp);
                		remainingPositions.add(userPendingTransactionTemp);
                	}
                	request.setAttribute("fundNames_p", fundNames);
                	request.setAttribute("remainingPositionList", remainingPositions);
                }
                request.setAttribute("positionList", positionList);
            } catch (Exception e) {
                errors.add("Unable to retrieve customer's position");
            }
            
            return successPage;

        } catch (Exception e) {
            errors.add(e.getClass()+"LLLL"+e.getMessage());
            errors.add("Unable to submit sell order");
            return originPage;
        }

    }
}